package ru.spb.osll.myfit.wikiverifier;

import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Vector;

import ru.spb.osll.myfit.common.Include;
import ru.spb.osll.myfit.common.Page;
import ru.spb.osll.myfit.common.PageElement;
import ru.spb.osll.myfit.common.Table;
import ru.spb.osll.myfit.common.TableCell;
import ru.spb.osll.myfit.common.TableCellResult;
import ru.spb.osll.myfit.common.TableStyle;
import ru.spb.osll.myfit.common.VerificationResult;
import ru.spb.osll.myfit.server.parser.TableElementParser;
import ru.spb.osll.myfit.server.templateloader.JarTableTemplateLoader;
import ru.spb.osll.myfit.server.templateloader.TableTemplateLoader;
import ru.spb.osll.myfit.wikiverifier.exception.TableStyleNotSupportedException;
import ru.spb.osll.myfit.wikiverifier.result.PageVerificationResult;
import ru.spb.osll.myfit.wikiverifier.result.TableVerificationResult;
import ru.spb.osll.myfit.wikiverifier.result.VerificationResultType;

public class WikiVerifierPageMarker {

  private WikiVerifier m_verifier;

  public WikiVerifierPageMarker(JarTableTemplateLoader templateLoader) {
    m_verifier = new WikiVerifier(getTemplates(templateLoader),
        templateLoader.getFixtureClasses());
  }

  public VerificationResult verifyPage(Page page) {
    boolean hasError = false;
    PageVerificationResult pageResult = m_verifier.verifyPage(page, false);
    ListIterator<TableVerificationResult> tableVerificationResults = pageResult
        .getTableResults().listIterator();

    ListIterator<PageElement> tableItr = page.getElements().listIterator();
    while (tableItr.hasNext() && tableVerificationResults.hasNext()) {
      PageElement element = tableItr.next();
      if (element instanceof Table) {
        TableVerificationResult result = tableVerificationResults.next();
        Table table = (Table) element;
        deleteErrorMark(table);
        if (result.getResult() != VerificationResultType.OK &&
            !(result.getException() instanceof TableStyleNotSupportedException)) {
          markTable(table, result);
          hasError = true;
        }
      }
    }

    for (PageElement pageElement : page.getElements()) {
      if (pageElement instanceof Include) {
        VerificationResult includedPageResult = verifyPage(((Include) pageElement)
            .getPage());
        hasError = hasError || includedPageResult.hasError();
      }
    }
    return new VerificationResult(page, hasError);
  }

  private List<Table> getTemplates(TableTemplateLoader templateLoader) {
    LinkedList<Table> templates = new LinkedList<Table>();
    TableElementParser parser = new TableElementParser();

    for (Class< ? > clazz : templateLoader.getFixtureClasses().values()) {
      Vector<String> rawTable = templateLoader.getTemplate(clazz.getName());
      Table template = parser.parseTable(rawTable);
      if (template.getData().size() > 0) {
        templates.add(template);
      }
    }

    return templates;
  }

  private void markTable(Table table, TableVerificationResult verificationResult) {
    ListIterator<Vector<TableCell>> rowsIterator = table.getData()
        .listIterator();
    while (rowsIterator.hasNext()) {
      Vector<TableCell> row = rowsIterator.next();
      markRow(row);
    }
    table.setStyle(TableStyle.UNKNOWN_FIXTURE);
  }

  // private void markOddRow(Vector<TableCell> row) {
  // ListIterator<TableCell> cellIterator = row.listIterator();
  // int i = 0;
  // while (cellIterator.hasNext()) {
  //
  // TableCell cell = cellIterator.next();
  // if (i % 2 == 0) {
  // cell.setTestResult(TableCellResult.ERROR);
  // }
  // i++;
  // }
  // }

  private void markRow(Vector<TableCell> row) {
    ListIterator<TableCell> cellIterator = row.listIterator();
    while (cellIterator.hasNext()) {
      TableCell cell = cellIterator.next();
      cell.setTestResult(TableCellResult.ERROR);
    }
  }

//  private void deleteErrorMark(Page page) {
//    ListIterator<PageElement> tableItr = page.getElements().listIterator();
//    while (tableItr.hasNext()) {
//      PageElement element = tableItr.next();
//      if (element instanceof Table) {
//        Table table = (Table) element;
//        deleteErrorMark(table);
//      }
//    }
//  }

  private void deleteErrorMark(Table table) {

    boolean hasError = false;
    ListIterator<Vector<TableCell>> rowsIterator = table.getData()
        .listIterator();
    while (rowsIterator.hasNext()) {
      Vector<TableCell> row = rowsIterator.next();
      ListIterator<TableCell> cellIterator = row.listIterator();
      while (cellIterator.hasNext()) {
        TableCell cell = cellIterator.next();
        if (cell.getTestResult() == TableCellResult.ERROR) {
          hasError = true;
          cell.setTestResult(TableCellResult.NONE);
        }
      }
    }
    
    if(hasError){
      table.setStyle(TableStyle.UNKNOWN_FIXTURE); 
    }
  }
}
